package org.arong.simpleweb4j;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RouteMappingFilter implements Filter {
	private Properties routeProp;
	private Properties dispatcherProp;
	private String routePropPath;
	private String dispatcherPropPath;

	public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		if(routeProp != null){
			HttpServletRequest request = (HttpServletRequest) req;
			HttpServletResponse response = (HttpServletResponse) resp;
			String className = null;
			String methodName = null;
			// 是否结束链流程
			boolean overChain = false;
			try {
				// 获取URI
				String uri = request.getRequestURI();
				String key = uri.replaceFirst(request.getContextPath() + "/", "");
				if(key.length() > 1 && key.charAt(key.length() - 1) == '/'){
					key = key.substring(0, key.length() - 1);
				}
				Object value = routeProp.get(key);
				if (value == null) {
					value = routeProp.get("/" + key);
				}
				if(value == null){
					value = routeProp.get(key + "/");
				}
				if(value == null){
					value = routeProp.get("/" + key + "/");
				}
				if (value != null) {
					className = value.toString().trim();
					Class<?> clazz = Class.forName(className);
					Object action = clazz.newInstance();
					// 获取方法参数
					methodName = request.getParameter("method");
					if (methodName == null || "".equals(methodName.trim())) {
						//如果参数中没有指定method参数，则默认执行work方法
						methodName = "work";
					}
					Method method;
					Object dispatcherPath;
					//如果action类继承了BaseAction，则将request及response注入action
					if(BaseAction.class.isAssignableFrom(clazz)){
						Method setRequestAndResponseMethod = clazz.getSuperclass().getDeclaredMethod("setRequestAndResponse", HttpServletRequest.class, HttpServletResponse.class);
						setRequestAndResponseMethod.invoke(action, request, response);
						method = clazz.getDeclaredMethod(methodName);
						dispatcherPath = method.invoke(action);
					}else{
						method = clazz.getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
						dispatcherPath = method.invoke(action, request, response);
					}
					//结束链流程
					overChain = true;
					if (dispatcherPath != null
							&& !"".equals(dispatcherPath.toString().trim())) {
						String disPath = (String) dispatcherPath;
						//如果配置了跳转映射
						if(dispatcherProp != null){
							if(dispatcherProp.get(disPath) != null){
								disPath = dispatcherProp.get(disPath).toString();
							}
						}
						req.getRequestDispatcher(disPath).forward(
								request, response);
					}
				}
			} catch (ClassNotFoundException e) {
				try {
					throw new Exception(routePropPath + "文件中的" + className
							+ "类不存在！");
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			} catch (SecurityException e) {
				try {
					throw new Exception(className + "类中没有找到无参构造方法！");
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			} catch (NoSuchMethodException e) {
				try {
					throw new Exception(className + "类中没有找到" + methodName + "方法");
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} finally {
				if (!overChain) {
					try{
						chain.doFilter(request, response);
					}catch(Exception e){
						System.err.println("========警告：" + className + "类的" + methodName + "方法推荐返回一个有意义的字符串========");
					}
				}
			}
		}else{
			chain.doFilter(req, resp);
		}

	}

	public void init(FilterConfig cfg) throws ServletException {
		// 获取路由映射文件名
		routePropPath = cfg.getInitParameter("routeMappingFilePath");
		// 获取跳转映射文件名
		dispatcherPropPath = cfg.getInitParameter("dispatcherMappingFilePath");
		try {
			if(routePropPath != null){
				routeProp = new Properties();
				routeProp.load(new FileReader(new File(RouteMappingFilter.class
						.getResource("/").getPath()
						+ routePropPath)));
			}
			if(dispatcherPropPath != null){
				dispatcherProp = new Properties();
				dispatcherProp.load(new FileReader(new File(
						RouteMappingFilter.class.getResource("/").getPath()
								+ dispatcherPropPath)));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void destroy() {

	}
}
